﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using HashCode;
using System.Configuration;

namespace XML
{
	/// <summary>
	/// Класс, в котором реализуются методы для работы с xml файлами.
	/// </summary>
	public static class ForXmlFiles
	{
		/// <summary>
		/// Метод возвращающий список файлов для копирования, прочитанный из xml файла.
		/// </summary>
		/// <param name="filepath">Путь к xml файлу.</param>
		/// <param name="sourcePath">Путь к папке с файлами, по которым считывается информация </param>
		/// <returns>Список типа InformationAboutFile.</returns>
		public static List<InformationAboutFile> ReadXmlDocument(string filepath, string sourcePath)
		{
			if (File.Exists(filepath))
			{
				// Объявляем и забиваем файл в документ
				XmlDocument xd = new XmlDocument();
				FileStream fs = new FileStream(filepath, FileMode.Open);
				xd.Load(fs);

				List<InformationAboutFile> listWithInfoAboutFilesForCopy = new List<InformationAboutFile>();
				XmlNodeList list = xd.GetElementsByTagName("File"); // Создаем и заполняем лист по тегу "File"

				for (int i = 0; i < list.Count; i++)
				{
					XmlAttributeCollection all = list[i].Attributes;
					XmlAttribute id = all["name"];
					XmlAttribute path = all["Path"];
					XmlAttribute chackSum = all["ChackSumm"];
					string pathFull = Path.Combine(sourcePath, path.InnerText);
					listWithInfoAboutFilesForCopy.Add(new InformationAboutFile(new FileInfo(pathFull), chackSum.InnerText));
				}

				return listWithInfoAboutFilesForCopy;
			}
			else
			{
				throw new FileNotFoundException();
			}
		}

        /// <summary>
        /// Получение значения атрибута с заданным именем.
        /// </summary>
        /// <param name="filePath">Путь к файлу.</param>
        /// <param name="fieldName">имя атрибута.</param>
        /// <returns>Значение атрибута.</returns>
		public static string GetConfigurationField(string filePath, string fieldName)
		{
			XmlDocument config = new XmlDocument();
			if (File.Exists(filePath))
			{
				using (FileStream Stream = new FileStream(filePath, FileMode.Open))
				{
					config.Load(Stream);
				}
				XmlElement root = config.DocumentElement;
				for (int i = 0; i < root.ChildNodes.Count; i++)
				{
					XmlNodeList xmlList = root.ChildNodes[i].ChildNodes;

					for (int j = 0; j < xmlList.Count; j++)
					{
						{
							foreach (XmlNode xmlParam in xmlList)
							{
								if (xmlParam.Attributes != null && (xmlParam.Name == "add" && xmlParam.Attributes["key"].Value == fieldName))
								{
									return xmlParam.Attributes["value"].Value;
								}
							}
						}
					}
				}
			}

			return string.Empty;
		}

        /// <summary>
        /// Задание значения атрибуту с заданным именем.
        /// </summary>
        /// <param name="filePath">Путь к файлу.</param>
        /// <param name="fieldName">Имя атрибута.</param>
        /// <param name="fieldValue">Новое значение атрибута.</param>
		public static void SetConfigurationField(string filePath, string fieldName, string fieldValue)
		{
			XmlDocument config = new XmlDocument();
			if (File.Exists(filePath))
			{
				using (FileStream Stream = new FileStream(filePath, FileMode.Open))
				{
					config.Load(Stream);
				}
				XmlElement root = config.DocumentElement;
				for (int i = 0; i < root.ChildNodes.Count; i++)
				{
					XmlNodeList xmlList = root.ChildNodes[i].ChildNodes;

					for (int j = 0; j < xmlList.Count; j++)
					{
						{
							foreach (XmlNode xmlParam in xmlList)
							{
								if (xmlParam.Attributes != null && (xmlParam.Name == "add" && xmlParam.Attributes["key"].Value == fieldName))
								{
									xmlParam.Attributes["value"].Value = fieldValue;
								}
							}
						}
					}
				}
			}
			config.Save(filePath);
		}

		/// <summary>
		/// Запись данных в xml файл.
		/// </summary>
		/// <param name="filepath">Путь к файлу, для записи.</param>
		/// <param name="files">Список с информацией для записи.</param>
		/// <param name="sourcePath">Путь к папке, из которой информация взята.</param>
		public static void WriteToXmlDocument(string filepath, List<InformationAboutFile> files, string sourcePath)
		{
			XmlDocument xd = new XmlDocument();
			FileStream fs = new FileStream(filepath, FileMode.Open);
			xd.Load(fs);
			DirectoryInfo targetDir = new DirectoryInfo(sourcePath);
			foreach (InformationAboutFile file in files)
			{
				XmlNode row = xd.CreateElement("File");
				xd.DocumentElement.AppendChild(row);
				XmlAttribute id = xd.CreateAttribute("name");
				id.Value = file.FileInfo.Name;
				row.Attributes.Append(id);
				XmlAttribute pathRow = xd.CreateAttribute("Path");
				pathRow.Value = file.FileInfo.FullName.Substring(targetDir.FullName.IndexOf(targetDir.Name) + targetDir.Name.Length + 1);
				row.Attributes.Append(pathRow);
				XmlAttribute hashRow = xd.CreateAttribute("ChackSumm");
				hashRow.Value = file.Hash;
				row.Attributes.Append(hashRow);
			}

			fs.Close();
			xd.Save(filepath);
		}

		/// <summary>
		/// Создает новый Xml файл.
		/// </summary>
		/// <param name="path">Путь к файлу.</param>
		/// <param name="startElement">Начальный элемент файла.</param>
		/// <returns>true-если создан файл, false в противном случае.</returns>
		public static bool CreateNewXmlFile(string path, string startElement)
		{
			try
			{
				XmlWriter xtw = new XmlTextWriter(path, Encoding.UTF8);
				xtw.WriteStartDocument();
				xtw.WriteStartElement(startElement);
				xtw.WriteEndDocument();
				xtw.Close();
				return true;
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
}
